﻿
using System.Windows;
using WPFSchematics.Definition.Common;
using WPFSchematics.Definition.Entities.Collection;

namespace WPFSchematics.Graphics.Ghosts
{
    /// <summary>
    /// 幻影Restore类。用于保存幻影实例，以及根据幻影实例复原对象。
    /// </summary>
    public class GhostRestore : IGhostRestore
    {
        /// <summary>
        /// 
        /// </summary>
        public GhostObject Ghost { get; private set; }

        /// <summary>
        /// 撤销变更。
        /// </summary>
        /// <param name="ghost"></param>
        private static void UndoChanged(GhostObject ghost)
        {
            ghost.ObserverHost.Observer.BeginRestore();

            for (var i = ghost.ChildRestores.Count - 1; i >= 0; i--)
            {
                ghost.ChildRestores[i].Undo();
            }
            var e = ghost.ChildProperties.GetEnumerator();

            while (e.MoveNext())
            {
                var kv = e.Current;

                if (kv.Value.OldValue != null && kv.Value.NewValue != null)
                {
                    ((DependencyObject)ghost.ObserverHost).SetValue(kv.Key, kv.Value.OldValue);
                }
            }
            
            ghost.ObserverHost.Observer.EndRestore();
        }

        /// <summary>
        /// 重做变更。
        /// </summary>
        /// <param name="ghost"></param>
        private static void RedoChanged(GhostObject ghost)
        {
            ghost.ObserverHost.Observer.BeginRestore();

            foreach (var r in ghost.ChildRestores)
            {
                r.Redo();
            }
            
            var e = ghost.ChildProperties.GetEnumerator();

            while (e.MoveNext())
            {
                var kv = e.Current;

                if (kv.Value.OldValue != null && kv.Value.NewValue != null)
                {
                    ((DependencyObject)ghost.ObserverHost).SetValue(kv.Key, kv.Value.NewValue);
                }
            }

            ghost.ObserverHost.Observer.EndRestore();
        }

        /// <summary>
        /// 添加。
        /// </summary>
        /// <param name="ghost">幻影。</param>
        /// <returns></returns>
        private static bool AddMember(GhostObject ghost)
        {
            var o = ((DependencyObject)ghost.CollectionPropertyOwner).GetValue(ghost.CollectionProperty);

            var flag = o is IOperateCollection;

            if (flag)
            {
                if (ghost.SnapMode)
                {
                    UndoChanged(ghost);
                }
                if (ghost.Index > -1)
                    ((IOperateCollection)o).Insert(ghost.Index, ghost.ObserverHost);
                else
                    ((IOperateCollection)o).Add(ghost.ObserverHost);
            }
            return flag;
        }

        /// <summary>
        /// 删除。
        /// </summary>
        /// <param name="ghost">幻影。</param>
        /// <returns></returns>
        private static bool DeleteMember(GhostObject ghost)
        {
            var o = ((DependencyObject)ghost.CollectionPropertyOwner).GetValue(ghost.CollectionProperty);

            var flag = o is IOperateCollection;

            if (flag)
            {
                ((IOperateCollection)o).Remove(ghost.ObserverHost);
            }
            return flag;
        }

        /// <summary>
        /// 撤销。
        /// </summary>
        public void Undo()
        {
            switch (Ghost.Type)
            {
                case GhostType.Added:
                    DeleteMember(Ghost);
                    break;
                case GhostType.Changed:
                    UndoChanged(Ghost);
                    break;
                case GhostType.Deleted:
                    AddMember(Ghost);
                    break;
            }
        }

        /// <summary>
        /// 重做。
        /// </summary>
        public void Redo()
        {
            switch (Ghost.Type)
            {
                case GhostType.Added:
                    AddMember(Ghost);
                    break;
                case GhostType.Changed:
                    RedoChanged(Ghost);
                    break;
                case GhostType.Deleted:
                    DeleteMember(Ghost);
                    break;
            }
        }

        /// <summary>
        /// 构造。
        /// </summary>
        /// <param name="ghost"></param>
        public GhostRestore(GhostObject ghost)
        {
            Ghost = ghost;
        }
    }
}
